/********************************************************************
	created:	2011-8-13   6:15
	author:		Lifan Su
	
	purpose:	test cases of functions in <cvt_int_mem.h>
*********************************************************************/

#include <cvt_int_mem.h>
#include <_cstdint.hpp>
#include <cstring>
#include <iostream>

using namespace std;

namespace {
    const uint8_t original[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,

        0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
        0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
        0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80,
        0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
    };

    uint8_t processed[64];

    const uint8_t  original_08 = UINT8_C(0xFE);
    const uint16_t original_16 = UINT16_C(0xFEDC);
    const uint32_t original_32 = UINT32_C(0xFEDCBA98);
    const uint64_t original_64 = UINT64_C(0xFEDCBA9876543210);

    uint8_t  processed_08;
    uint16_t processed_16;
    uint32_t processed_32;
    uint64_t processed_64;

    const uint8_t  int08_be = UINT8_C(0x00);
    const uint8_t  int08_le = UINT8_C(0x00);
    const uint16_t int16_be = UINT16_C(0x0001);
    const uint16_t int16_le = UINT16_C(0x0100);
    const uint32_t int32_be = UINT32_C(0x00010203);
    const uint32_t int32_le = UINT32_C(0x03020100);
    const uint64_t int64_be = UINT64_C(0x0001020304050607);
    const uint64_t int64_le = UINT64_C(0x0706050403020100);

    const uint8_t arr08_be[] = {0xFE};
    const uint8_t arr08_le[] = {0xFE};
    const uint8_t arr16_be[] = {0xFE, 0xDC};
    const uint8_t arr16_le[] = {0xDC, 0xFE};
    const uint8_t arr32_be[] = {0xFE, 0xDC, 0xBA, 0x98};
    const uint8_t arr32_le[] = {0x98, 0xBA, 0xDC, 0xFE};
    const uint8_t arr64_be[] = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};
    const uint8_t arr64_le[] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE};

    const uint8_t  cvti08 = UINT8_C(0xFE);
    const uint16_t cvti16 = UINT16_C(0xDCFE);
    const uint32_t cvti32 = UINT32_C(0x98BADCFE);
    const uint64_t cvti64 = UINT64_C(0x1032547698BADCFE);

    const uint8_t cvta08[] = {0x00};
    const uint8_t cvta16[] = {0x01, 0x00};
    const uint8_t cvta32[] = {0x03, 0x02, 0x01, 0x00};
    const uint8_t cvta64[] = {0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};


}

void clear()
{
    processed_08 = (uint8_t)(processed_16 = processed_32 = (uint32_t)(processed_64 = 0));
    memset(processed, 0, 64);
}

bool test_arr_to_be()
{
    return int08_be == cvt_byte_to_u08_be(original)
        && int16_be == cvt_byte_to_u16_be(original)
        && int32_be == cvt_byte_to_u32_be(original)
        && int64_be == cvt_byte_to_u64_be(original);
}

bool test_arr_to_le()
{
    return int08_le == cvt_byte_to_u08_le(original)
        && int16_le == cvt_byte_to_u16_le(original)
        && int32_le == cvt_byte_to_u32_le(original)
        && int64_le == cvt_byte_to_u64_le(original);
}

bool test_be_to_arr()
{
    cvt_u08_be_to_byte(processed + 0x00, original_08);
    cvt_u16_be_to_byte(processed + 0x10, original_16);
    cvt_u32_be_to_byte(processed + 0x20, original_32);
    cvt_u64_be_to_byte(processed + 0x30, original_64);

    return !memcmp(processed + 0x00, arr08_be, 1)
        && !memcmp(processed + 0x10, arr16_be, 2)
        && !memcmp(processed + 0x20, arr32_be, 4)
        && !memcmp(processed + 0x30, arr64_be, 8);
}

bool test_le_to_arr()
{
    cvt_u08_le_to_byte(processed + 0x00, original_08);
    cvt_u16_le_to_byte(processed + 0x10, original_16);
    cvt_u32_le_to_byte(processed + 0x20, original_32);
    cvt_u64_le_to_byte(processed + 0x30, original_64);

    return !memcmp(processed + 0x00, arr08_le, 1)
        && !memcmp(processed + 0x10, arr16_le, 2)
        && !memcmp(processed + 0x20, arr32_le, 4)
        && !memcmp(processed + 0x30, arr64_le, 8);
}

bool test_cvt_int()
{
    return cvti08 == cvt_u08_endian(original_08)
        && cvti16 == cvt_u16_endian(original_16)
        && cvti32 == cvt_u32_endian(original_32)
        && cvti64 == cvt_u64_endian(original_64);
}

bool test_cvt_arr()
{
    cvt_b08_endian(processed + 0x00, original);
    cvt_b16_endian(processed + 0x10, original);
    cvt_b32_endian(processed + 0x20, original);
    cvt_b64_endian(processed + 0x30, original);

    return !memcmp(processed + 0x00, cvta08, 1)
        && !memcmp(processed + 0x10, cvta16, 2)
        && !memcmp(processed + 0x20, cvta32, 4)
        && !memcmp(processed + 0x30, cvta64, 8);
}

int _cdecl main()
{
    cout << boolalpha;

    cout << "test_arr_to_be():  " << test_arr_to_be() << endl;
    clear();
    cout << "test_arr_to_le():  " << test_arr_to_le() << endl;
    clear();
    cout << "test_be_to_arr():  " << test_be_to_arr() << endl;
    clear();
    cout << "test_be_to_arr():  " << test_be_to_arr() << endl;
    clear();
    cout << "test_cvt_int():  " << test_cvt_int() << endl;
    clear();
    cout << "test_cvt_arr():  " << test_cvt_arr() << endl;

    cin.get();
}